<script>
import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import * as olProj from "ol/proj"; // 坐标变换使用
import DragPan from "ol/interaction/DragPan";
import * as olControl from "ol/control"; // 关闭缩放等控制功能
import * as olInteraction from "ol/interaction"; // 用来关闭原有的鼠标交互操作
// geo矢量
import GeoJSON from "ol/format/GeoJSON";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
// Feature
import Feature from "ol/Feature";
import LineString from "ol/geom/LineString";
// 样式设置
import { Fill, Stroke, Style, Text } from "ol/style";
import MousePosition from "ol/control/MousePosition"; // 鼠标位置
import * as olCoordinate from "ol/coordinate";
import * as olExtent from "ol/extent"; // 范围信息

// 配置文件
import mapconfig from "../../public/config/mapconfig.js";
import mapBase from "./ol/common/mapBase.js"; // 基础功能
import mapProj from "./ol/common/mapProj.js"; // 添加EPSG:4490
import mapStyle from "./ol/common/mapStyle.js"; // 样式功能
import mapFlash from "./ol/common/mapFlash.js"; // 闪烁
import mapBubble from "./ol/common/mapBubble.js"; // 气泡

import boundarLayer from "./ol/layers/boundaryLayer.js"; // 边界层
import MapLayer from "./ol/layers/mapLayer.js"; // 根据地图服务的不同，加载不同的地图底图（wmx，xyz）
import GridLayer from "./ol/layers/gridLayer.js"; // 网格层（经纬线）
import ShareLayer from "./ol/layers/shareLayer.js"; // 共享层（公用:如，标绘的范围框）
import HeatmapLayer from "./ol/layers/heatmapLayer.vue";
import CoordLayer from "./ol/layers/coordLayer.js";
import POILayer from "./ol/POILayer.vue"; // POI层new
import AnimLayer from "./ol/animating/animLayer.vue";
import PlottingLayer from "./ol/plotting/plottingLayer.vue"; // 标绘层
import PlotMapIO from "./ol/plugin/plotMapIO.js"; // 标绘Map接口（包含方案标绘的地图接口）

import Bubble from "./ol/bubble.vue"; // 气泡生成(前端提供的创建div气泡元素，实际创建汽包在mapBubble中)
import printer from "./ol/printer.vue";
import axios from "axios";
import iDrawing from "./ol/drawing/drawing.js";
import iAnimLayerIO from "./ol/animating/animLayerIO.js";
import iLayerIO from "./ol/layers/layerIO.js";
import ScaleLine from "ol/control/ScaleLine"; // 比例尺添加
import PathAnimIO from "./ol/pathAnim/pathAnimIO.js"; // 添加路径动画-new
// 初始化测试数据（测试完成后 要删除）
import { testData } from "./ol/testdata/tData01.js";
import OpenPlotFiles from "./ol/plotting/openPlotFile.js";
import { defineComponent, getCurrentInstance } from "vue";

export default defineComponent({
  mixins: [
    MapLayer,
    GridLayer,
    ShareLayer,
    mapBase,
    mapStyle,
    boundarLayer,
    mapFlash,
    mapBubble,
    mapProj,
    PlotMapIO,
    iDrawing,
    iAnimLayerIO,
    iLayerIO,
    PathAnimIO,
    CoordLayer,
    OpenPlotFiles,
  ],
  components: {
    POILayer,
    Bubble,
    PlottingLayer,
    HeatmapLayer,
    printer,
    AnimLayer,
  },
  props: {
    mapId: {
      type: String,
      default: "map-container",
    },
    mapWidth: {
      type: String,
    },
    mapHeight: {
      type: String,
    },
  },
  setup(props, { emit }) {
    const { proxy } = getCurrentInstance();

    const initState = () => {
      const state = reactive({
        selTest: null,
        selColor: "#FF0000", // 用户选择的颜色（标绘）
        imap: null,
        conf: "", // 配置文件
        bbox: null, // 范围盒 -- [minx, miny, maxx, maxy]
        bestview: null, // 最佳视角
        // 地图展示信息
        mapDefStyle: null, // 地图边界线缺省样式
        curRegion: "china", // 当前地图展示区域''
        currLevel: 4, // 当前地图展示级别
        centerPos: [114.064839, 22.548857], // 中心点坐标[]
        mapList: [], // 地图选择顺序列表[{区域，显示级别，中心点}, ... ] 方便返回
        // 基本地图层
        baseMapLayer: null, // 基础题图层--底图
        extMapLayer: null, // 附加信息层--交通路线、区域范围等 extra
        geoMapLayer: null, // 边界范围层--边界访问
        gridLayer: null, // 网格图层（公里格，bbox框）
        featureOverlay: null, // 边界选择层
        // 样式
        sMapType: "classic", // 默认为经典地图
        sIconType: "standard", // 用户使用的图标类型图标
        aStyleList: [], // 地图所用样式数组，保存所有地图样式（线条，多边形，图像）
        // 交互Interaction
        iSelect: undefined, // 选中的边界数据(用来保存选中的边界feature)
        iSelPlotID: null, // 当前用于选中的军标ID
        iAction: null, // 当前地图操作行为[画图，测量，区域选择，等]
        iActType: null, // 当前操作- 详细类型[画图：圆形，方形，等]
        selFeature: null, // drawing 绘制平移时选中的feature
        // 交互Interaction-pointer：军标修改拖动
        dragPan: null, // 保存地图的dragPan方法，军标修改时关闭
        isMouseDown: false, // 鼠标按下状态，军标修改时记录鼠标状态
        coordinate_: null, // 记录军标修改时，上次鼠标位置
        feature_: null, // 修改时选中的军标对象
        hideLevel: 12, // 边界隐藏级别，false为无效
        map: "",
        iBubble: "",
        iHeatmap: "",
        iPoi: "",
        iAnim: "",
        iPlotting: "",
        Prt: "",
      });

      return toRefs(state);
    };

    const {
      selTest,
      selColor,
      imap,
      conf,
      bbox,
      bestview,
      mapDefStyle,
      curRegion,
      currLevel,
      centerPos,
      mapList,
      baseMapLayer,
      extMapLayer,
      geoMapLayer,
      gridLayer,
      featureOverlay,
      sMapType,
      sIconType,
      aStyleList,
      iSelect,
      iSelPlotID,
      iAction,
      iActType,
      selFeature,
      dragPan,
      isMouseDown,
      coordinate_,
      feature_,
      hideLevel,
      map,
      iBubble,
      iHeatmap,
      iPoi,
      iAnim,
      iPlotting,
      Prt,
    } = initState();

    watch(
      () => iSelPlotID.value,
      () => {
        PlottingLayer.mixins[0].methods.getPlotDataByID(iSelPlotID.value, conf.value.RCS);
      }
    );

    conf.value = mapconfig;

    // -- 测试打开标绘文件
    const showPlotFile = (sPlotID, bReadonly = true) => {
      openPlotFile(sPlotID, imap.value); // 改到组件内部后，imap.value 可以省略
    };
    // -- 测试方法设置聚集融合长度
    const setClusterDistance = (iDist) => {
      POILayer.methods.setDistance(iDist);
    };
    // -- 测试方法，设置是否使用聚集
    const toggleCluster = () => {
      POILayer.methods.togglePOILayerType(false);
    };
    // 显示网格（经纬度）
    const showGrid = () => {
      createGridLayer(imap.value);
    };
    const hideGrid = () => {
      destroyGridLayer(imap.value);
    };
    /**
     * @description 根据提供的数据渲染地图要素
     * @param oSourceData {Object}  要显示的地图元素数据
     * @param sDataType {String}  本次处理的数据类型（poi，scatter， heat，line，poly，rang ...）
     * @return 无
     */
    const showData = (oSourceData, sDataType) => {
      const sType = sDataType.toLowerCase();
      switch (sType) {
        case "poi":
        case "scatter":
        case "line":
        case "poly":
        case "range":
          POILayer.methods.showPOIExt(oSourceData); // oSourceData.data
          if (proxy.bShowTopLabel) {
            // 此标志在mapBubble中，是否开启顶牌标志；新添加的标志
            showAllMarkerExt("poiLayer", "simple", imap.value); // 如果打开了顶部标签，载入时打开标签
          } else {
            showAllMarker("poiLayer", imap.value); // 在mapBubble.js （闪烁和气泡统一处理）；使用原来的方法，只有isPop的数据显示气泡
          }
          break;
        case "heat":
          // heatmap展示热力图数据
          iHeatmap.value.showHeatData(oSourceData, imap.value); // oSourceData.data
          break;
        case "anim":
          if (iAnim.value.hasAnimLayer()) {
            iAnim.value.showAnimData(oSourceData);
          } else {
            iAnim.value.initAnimLayer(
              imap.value,
              aStyleList.value,
              sIconType.value
            );
            iAnim.value.showAnimData(oSourceData);
          }
          break;
        default:
          console.log("无效数据！");
      }
    };

    // 根据返回的数据进行分析，调用不同的接口处理（废弃--不满足需求）
    const showData2 = (oSourceData) => {
      // 显示POI数据
      if (oSourceData.hasOwnProperty("data")) {
        POILayer.methods.showPOIExt(oSourceData.data);
        showAllMarker("poiLayer", imap.value); // 在mapBubble.js （闪烁和气泡统一处理）
      }
      // 显示热力图数据
      if (oSourceData.hasOwnProperty("heat")) {
        // heatmap展示热力图数据
        iHeatmap.value.showHeatData(oSourceData.heat, imap.value);
      }
      // 显示标绘数据
      console.log("plotting: ", oSourceData.hasOwnProperty("plot"));
      if (oSourceData.hasOwnProperty("plot")) {
        POILayer.methods.showPOI(oSourceData.plot);
      }
    };

    // 闪烁测试
    const stopFlash = () => {
      clearAllflash(imap.value);
      clearAllBubble(imap.value);
    };
    // POI数据调用
    const getPOIData = () => {
      const oD = testData.getHeatGridData();
      showData(oD.data, "heat");
    };
    // 测试缩放
    const setScale = () => {
      const iUnit = PlottingLayer.methods.getUnit();
      PlottingLayer.mixins[0].methods.setUnit(iUnit[0] * 10, iUnit[1] * 10);
    };
    // 测试-获取文字控制点2
    const txtPnts = () => {
      PlottingLayer.methods.getTxtCtrlPnt(iSelPlotID.value);
    };
    /* 【打印区域】 -- 放置与打印相关的代码IO */
    // 获取png地图数据
    const getPNGMap = (pageFormat, dpi, opt) => {
      // 获取图PNG的地图
      Prt.value.getPNG(pageFormat, dpi, opt);
    };
    const printPNG = () => {
      // Prt.value.print2PNG()
      Prt.value.print2PNG();
    };
    const printPDF = (pageFormat, dpi) => {
      Prt.value.print2PDF(pageFormat, dpi);
    };

    /* 【标绘区域】 -- 防止和标会相关的代码IO */
    // 显示plotPanel; ！此面板后续会改变
    // 设置标绘面板是否显示：参数isDSP：ture，false （isDisplay）
    const showPlotPanel = (iShow) => {
      PlottingLayer.methods.showPlotPanel(iShow);
    };
    // 文字尺寸调整（提供给打印使用）
    const zoomTxt = () => {
      // 调用子类的同名方法
      PlottingLayer.methods.zoomTxt();
    };
    // 军标放大：设置unit，初始时放大（需要统一，只能一次！整个绘制期间要保持一致）
    const plotScale = (zoomin = true) => {
      let iUnit = PlottingLayer.methods.getUnit();
      if (zoomin) {
        PlottingLayer.mixins[0].methods.setUnit(iUnit[0] + 500, iUnit[1] + 500);
      } else {
        PlottingLayer.mixins[0].methods.setUnit(iUnit[0] - 500, iUnit[1] - 500);
      }
      iUnit = PlottingLayer.methods.getUnit();
      if (iUnit[0] < 200) {
        PlottingLayer.mixins[0].methods.setUnit(200, 200);
      }
      if (iUnit[0] > 200000) {
        PlottingLayer.mixins[0].methods.setUnit(200000, 200000);
      }
    };
    // 保存-获取保存的军标数据
    const getSaveData = () => {
      const res = PlottingLayer.mixins[1].methods.saveData();
      return res
    };
    // 加载-将数据载入
    // 参数plotData：加载到的数据
    const setLoadData = (plotData) => {
      const iData = plotData;
      // 标绘文件ID
      if (iData.fileID) {
        // 设置标绘文件ID
        PlottingLayer.methods.setPlotFileID(iData.fileID);
      } else {
        // 没有就创建一个ID
        // const newID = PlottingLayer.methods.createPlotFileID()
        // PlottingLayer.methods.setPlotFileID(newID)
        console.log("标绘文件没有id！");
        
      }
      // 数据格式plotData = {unit: [500,500], strokeWidth: 2, data:'[~]'}
      if (iData.unit && iData.unit instanceof Array) {
        // 设置标绘的基本尺寸
        

        PlottingLayer.mixins[0].methods.setUnit(iData.unit[0], iData.unit[1]);
      } else {
        // 设置标绘的基本尺寸，默认值（500*500）
        PlottingLayer.mixins[0].methods.setUnit(500, 500);
      }
      if (iData.strokeWidth) {
        // 设置基础的线宽
        
        PlottingLayer.mixins[0].methods.setStrokeWidth(iData.strokeWidth);
      } else {
        PlottingLayer.mixins[0].methods.setStrokeWidth(2);
      }
      // 获取数据使用的坐标系统（保存地图时，使用的地图坐标）
      if (!iData.RCS) {
        // 如果没有此数据，返回不做处理; 改成RCS空时，设为EPSG:3857
        // console.log('保存的数据缺少RCS，请确认后再导入')
        // return null
        iData.RCS = "EPSG:3857";
        PlottingLayer.methods.loadData2(iData.data, iData.RCS, conf.value.RCS);
      } else if (iData.RCS === conf.value.RCS) {
        // 设置基础的线宽
        // 坐标系统一致，直接处理即可
        if (iData.data) {
          PlottingLayer.mixins[1].methods.loadData(iData.data);
        }
      } else {
        // 坐标系统不一致，需要进行坐标转换
        if (iData.data) {
          PlottingLayer.methods.loadData2(iData.data, iData.RCS, conf.value.RCS);
        }
      }
      zoomTxt(); // 调整载入文字大小
    };

    const createPlotFileID = () => {
      return iPlotting.value.createPlotFileID();
    };

    // 从文件载入军标（文件-->标绘界面--用于保存到数据库）
    /**
     * @param null
     */
    const loadPlotfromFile = () => {
      const fileInput = document.getElementById("file");
      const targetFile = fileInput.files[0];
      const name = targetFile.name;
      const size = targetFile.size;
      const sType = targetFile.type;
      if (sType === "application/json") {
        const reader = new FileReader();
        reader.readAsText(targetFile); // .readAsDataURL
        reader.onload = function () {
          const data = reader.result; // base64形式的文件内容
          const plotData = JSON.parse(data);
          // console.log(plotData['地图信息']['军标信息'])
          const iData = plotData["地图信息"]["军标信息"];
          // 数据格式plotData = {unit: [500,500], strokeWidth: 2, data:'[~]'}
          if (iData.unit && iData.unit instanceof Array) {
            // 设置标绘的基本尺寸
            PlottingLayer.mixins[0].methods.setUnit(iData.unit[0], iData.unit[1]);
          } else {
            // 设置标绘的基本尺寸，默认值（500*500）
            PlottingLayer.mixins[0].methods.setUnit(500, 500);
          }
          if (iData.strokeWidth) {
            // 设置基础的线宽
            PlottingLayer.mixins[0].methods.setStrokeWidth(iData.strokeWidth);
          } else {
            PlottingLayer.mixins[0].methods.setStrokeWidth(2);
          }
          // 目前只按照坐标系一致进行导入，其他参考上面代码更改--setload
          if (iData.data) {
            PlottingLayer.mixins[1].methods.loadData(iData.data);
            // 需要将xdata数据结构转成数据库的存储结构
            // PlottingLayer.methods.savexData2DB(iData.data)
          }
        };
        reader.onerror = function () {
          console.log("读取失败");
          console.log(reader.error);
        };
      }
    };
    /**
     * 将xData中的所有标绘数据保存到数据库--用于从文件导入标绘数据，然后保存！
     */
    const savexData2DB = () => {
      PlottingLayer.methods.savexData2DB();
    };
    // 选择标绘军标idplotID
    const selectPlot = (plotID) => {
      // 如果调用的军标ID和之前一样，直接绘制
      if (iActType.value === plotID) {
        // 调用开始绘制
        PlottingLayer.methods.beginPlotting(plotID);
      } else {
        // 否则需要重新调用军标（异步需要等待！）
        iActType.value = plotID;
        PlottingLayer.methods.getPlotData(plotID); // 调用军标数据；// 调用plottinglayer方法，其内部使用vec的get-PlotDataEx方法
        PlottingLayer.methods.setPlotType(plotID); // 修改plottingLayer.iType;触发draw事件绘制
      }
    };
    // 修改军标颜色
    const onColorChange = () => {
      // 颜色发生变化时，需要调用标会的setPlotColor方法修改颜色
      PlottingLayer.methods.setPlotColor(selColor.value);
    };

    /* 【环境配置】 -- 设置环境变量和参数 */
    // 设置当前操作--调整
    const onAdjust = () => {
      iActType.value = "adjust";
    };
    // 获取交互的功能方法（关闭用--标绘是需要停止拖拽功能）
    // 是否放到开始标会中比较合适？
    const getFun = () => {
      let pan;
      imap.value.getInteractions().forEach((element) => {
        if (element instanceof DragPan) {
          pan = element;
        }
      });
      return pan;
    };
    // 框选放大功能（用来匹配鼠标拖拽产生的范围）
    // 参数：boxCoord = [minx, miny, maxx, maxy] 范围盒
    const boxZoom = (boxCoord = bbox.value) => {
      if (!boxCoord) return;
      const iView = imap.value.getView(); // 获取当前地图的view
      const iSize = imap.value.getSize(); // 获取地图的尺寸
      // 获取用户框定的坐标范围
      const extent = boxCoord; // [0,0,10000,10000] [[0,0],[10000,0],[10000,10000],[0,10000]]
      const resolution = iView.getResolutionForExtent(extent, iSize); //  以提供范围和尺寸，获取分辨率
      var center = olExtent.getCenter(extent);
      // 设置缩放时动画效果
      iView.animate({
        resolution: resolution, // 动画结束时视图的分辨率。如果zoom还提供，则将忽略此选项。
        center: center, // 动画结束时视图的中心
        // duration: proxy.duration_,  // 动画的持续时间（以毫秒为单位）
        // easing: ol.easing.easeOut  // 动画期间使用的缓动功能
      });
    };

    // 计算数组中所有值的最大和最小值（提出到imapBase.js中）
    // 返回：方位盒 [minx, miny, maxx, maxy]
    const getMinMax = (geoCoord) => {
      const coordArray = geoCoord[0];
      const iNum = coordArray.length; // 边界坐标数组
      if (iNum === 0) return null;
      const mixArr = [coordArray[0][0], coordArray[0][1]]; // 坐标最小值
      const maxArr = [coordArray[0][0], coordArray[0][1]]; // 坐标最大值
      let currVal;
      for (let i = 1; i < iNum; i++) {
        currVal = coordArray[i];
        // 当前值的x小于最小值x
        if (currVal[0] < mixArr[0]) {
          mixArr[0] = currVal[0];
        }
        if (currVal[1] < mixArr[1]) {
          mixArr[1] = currVal[1];
        }
        // 当前值大于最大值
        if (currVal[0] > maxArr[0]) {
          maxArr[0] = currVal[0];
        }
        if (currVal[1] > maxArr[1]) {
          maxArr[1] = currVal[1];
        }
      }
      // 返回 [minx, miny, maxx, maxy] 范围盒
      return [mixArr[0], mixArr[1], maxArr[0], maxArr[1]];
    };
    // 获取区域边界数据行政区域数据
    // ！要添加样式的修改；省市区的边界是不一样的（一个点，两个点，三个点），颜色和宽度的设置
    // 参数： province省份； city 市； area 区
    const getRegionData = (province, city = null, area = null) => {
      let geojsonUrl = null;
      if (area) {
        geojsonUrl = "/mapres/maps/json/" + city + ".json";
      } else if (city) {
        geojsonUrl = "/mapres/maps/json/" + province + ".json";
      } else if (province) {
        geojsonUrl = "/mapres/maps/json/china.json";
      } else {
        return null;
      }
      return new Promise(function (resolve) {
        axios.get(geojsonUrl).then((res) => {
          resolve(res);
        });
      });
    };

    const getRegionDataByName = (sRegionName) => {
      if (!sRegionName) return;
      const geojsonUrl = "/mapres/maps/json/" + sRegionName + ".json";
      return new Promise(function (resolve) {
        axios.get(geojsonUrl).then((res) => {
          resolve(res);
        });
      });
    };
    // 根据行政区域名称，获取范围盒
    // 参数：province省份； city 市； area 区
    // 返回：boundingBox区域边界的方位框 ？有坐标转换！
    const getBBoxByName = async (province, city = null, area = null) => {
      if (!province) return null;
      let targetName = null;
      // 设置查找区域名称
      if (area) {
        targetName = area;
      } else if (city) {
        targetName = city;
      } else if (province) {
        targetName = province;
      }
      const regionData = await getRegionData(province, city, area); // 获取区域json数据
      const iFeatures = regionData.data.features;
      let iGeometry = null;
      for (let i = 0; i < iFeatures.length; i++) {
        const iName = iFeatures[i].properties.name;
        if (iName === targetName) {
          iGeometry = iFeatures[i].geometry;
          break;
        }
      }
      if (!iGeometry) return;
      let geoType = iGeometry.type;
      let boundingBox = null;
      geoType = geoType.toLowerCase();
      if (geoType === "polygon") {
        boundingBox = getMinMax(iGeometry.coordinates); // bbox.value
      }
      if (geoType === "multipolygon") {
        const paraArr = iGeometry.coordinates[0];
        boundingBox = getMinMax(paraArr); // bbox.value
      }
      // 地图获取的坐标是EPSG:4326的，如果和当前使用的不一致
      if (conf.value.RCS.toLowerCase() !== "epsg:4326") {
        const a = [boundingBox[0], boundingBox[1]]; // a临时坐标
        const b = [boundingBox[2], boundingBox[3]]; // b临时坐标
        const aa = olProj.transform(a, "EPSG:4326", conf.value.RCS); // aa转换成当前投影的坐标
        const bb = olProj.transform(b, "EPSG:4326", conf.value.RCS); // bb转换成当前投影的坐标
        bbox.value = [aa[0], aa[1], bb[0], bb[1]];
      } else {
        bbox.value = boundingBox;
      }
      // 改成坐标转换后的新坐标（后续可以直接使用）
      return bbox.value;
    };
    // 更新BBox数据
    // 通过参数提供的坐标点数组，计算新的范围盒，更新并调整到正确显示
    const updateBBox = (ctrlPntLs) => {
      let boundingBox = null;
      boundingBox = getMinMax(ctrlPntLs);
      bbox.value = boundingBox;
      // 更新范围盒显示
      // 参数：boxCoord = [minx, miny, maxx, maxy] 范围盒;默认 参数bbox.value
      boxZoom();
    };
    /* Method: displayOverLayer 选择交互方式变更
     * 如果交互方式变更，重新生成选择交互方式（hover）
     * 参数：
     * 返回：
     */
    const displayOverLayer = (pixel) => {
      // 根据选择边界信息展示或隐藏
      // console.log(imap.value.getLayers())
      geoMapLayer.value.getFeatures(pixel).then((features) => {
        const feature = features.length ? features[0] : undefined;
        if (feature !== iSelect.value) {
          if (iSelect.value) {
            featureOverlay.value.getSource().removeFeature(iSelect.value);
          }
          if (feature) {
            featureOverlay.value.getSource().addFeature(feature);
          }
          iSelect.value = feature;
        }
      });
    };
    /* Method: clearSelectZone 清除鼠标选择的区域边界
     * 如果有选择的区域边界，删除
     */
    const clearSelectZone = () => {
      if (iSelect.value) {
        featureOverlay.value.getSource().removeFeature(iSelect.value);
        iSelect.value = null;
      }
    };
    /**
     * @description 使用cardMap的第一步，初始化地图资源，初始化底图
     * @param 无
     * @return 无
     */
    const initSource = () => {
      // 缺省样式（style）初始化
      proxy.clearStyleList(aStyleList.value); // 清空样式列表数组（mapStyle中）
      // 循环创建配置文件中对的样式，写入样式列表
      const styleArr = conf.value.STYLE_LIST; // 配置文件缺省样式数组
      for (let i = 0; i < styleArr.length; i++) {
        if (styleArr[i].class) {
          // 样式数据对象，样式名称，样式列表数组
          proxy.addStyle2StyleList(
            styleArr[i],
            styleArr[i].class,
            aStyleList.value
          );
        }
      }
      // 缺省地图边界样式确认（没有则加载）
      if (!aStyleList.value.mapDefStyle) {
        proxy.createDefStyle("mapDefStyle", aStyleList.value);
      }
      if (!aStyleList.value.mapSelStyle) {
        proxy.createDefStyle("mapSelStyle", aStyleList.value);
      }

      // 创建基本地图层
      baseMapLayer.value = proxy.createMapLayer(
        conf.value.classic.base,
        conf.value
      ); // 在mapLayer.js中
      // 创建扩展地图层（如，道路信息层,或者叠加区域图层）
      if (conf.value.classic.ext) {
        extMapLayer.value = proxy.createMapLayer(
          conf.value.classic.ext,
          conf.value
        ); // 在mapLayer.js中
      }

      // 设置显示矢量边界层（区域名称，图层样式） boundaryLayer + mapDefStyle; （创建geoMapLayer.value = new VectorLayer）
      geoMapLayer.value = proxy.createBoundaryLayer(
        "china",
        aStyleList.value.mapDefStyle
      ); // 在mapDefStyle.js

      // 创建鼠标选中边界选择层 有（样式） featureOverlay.value = new VectorLayer
      featureOverlay.value = proxy.createBoundaryOverlay(
        aStyleList.value.mapSelStyle
      ); // 在boundaryLayer.js

      // 调整层级关系
      baseMapLayer.value.setZIndex(0);
      if (extMapLayer.value) {
        extMapLayer.value.setZIndex(1);
      }
      // 地图范围边框层
      geoMapLayer.value.setZIndex(5);
      featureOverlay.value.setZIndex(99); // 地图选中边框展示
    };
    /* Method: initMap地图初始化
     * 根据创建的图层，创建地图实例
     * 参数：
     * 返回：
     */
    const initMap = () => {
      if (imap.value) {
        imap.value = null;
      }
      // 地图层显示
      let iMapLayerList = null;
      const cp = olProj.transform(centerPos.value, "EPSG:4326", conf.value.RCS);
      centerPos.value = cp; // 坐标系统
      if (extMapLayer.value) {
        iMapLayerList = [
          baseMapLayer.value,
          extMapLayer.value,
          geoMapLayer.value,
          featureOverlay.value,
        ];
      } else {
        iMapLayerList = [
          baseMapLayer.value,
          geoMapLayer.value,
          featureOverlay.value,
        ];
      }
      // 添加比例尺
      const scaleLineControl = new ScaleLine(); // 定义比例尺控件
      // 创建View，新添加，用来提供范围限制
      const aExtent = conf.value.extent;
      const fMinZoom = conf.value.minZoom || 3;
      const fMaxZoom = conf.value.maxZoom || 18;
      // -- view创建 --
      let myView = null;
      if (aExtent && Array.isArray(aExtent) && aExtent.length === 4) {
        myView = new View({
          projection: conf.value.RCS, // conf.value.RCS, // MAP_SRS, // 'EPSG:4326',3857
          center: centerPos.value, // proj.fromLonLat(116.401969, 39.913385), // cp, 106.51, 29.55
          zoom: conf.value.zoom,
          minZoom: fMinZoom,
          maxZoom: fMaxZoom,
          extent: aExtent,
        });
      } else {
        myView = new View({
          projection: conf.value.RCS,
          center: centerPos.value,
          zoom: conf.value.zoom,
          minZoom: fMinZoom,
          maxZoom: fMaxZoom,
        });
      }
      imap.value = new Map({
        target: props.mapId, // target: 'map-container',
        // 设置地图控件，默认的三个控件都不显示
        controls: olControl
          .defaults({
            attribution: false,
            rotate: false,
            zoom: false,
          })
          .extend([
            new MousePosition({
              coordinateFormat: olCoordinate.createStringXY(4),
              projection: "EPSG:4326",
              target: document.getElementById("mouse-position"),
            }),
            scaleLineControl,
          ]),
        // 让所有的zoom开关都设置为false
        interactions: olInteraction.defaults({
          dragPan: true,
          doubleClickZoom: false,
          shiftDragZoom: false,
          pinchZoom: false,
        }),
        layers: iMapLayerList,
        view: myView,
      });
    };
    /* Method: mapRefresh
     * 刷新地图，如果地图尺寸修改后，需要刷新地图
     * 参数：
     * 返回：
     */
    const mapRefresh = () => {
      // 暂时只提供尺寸刷新，后续根据情况添加其他内容
      imap.value.updateSize();
    };
    /**
     * @description 切换使用的图标类型
     * @param sTypeName {String} 图标名称
     * @return
     */
    const switchIconType = (sTypeName) => {
      if (sIconType.value === sTypeName) {
        return;
      }
      // 切换(修改sIconType变量，此变量从mapStyle处集成)
      sIconType.value = sTypeName;
      POILayer.methods.sIconType = sTypeName;
      proxy.delStyleByImage(aStyleList.value);
      // 需要重新绘制图标（数据保存在哪了？ goto）
    };
    /**
     * @description 根据选择的地图类型切换地图
     * @param sMapTypeName {String} 地图样式名称
     * @return
     */
    const switchMap = (sMapTypeName) => {
      if (sMapType.value === sMapTypeName) {
        return;
      }
      const oMapInfos = conf.value[sMapTypeName];
      if (oMapInfos) {
        if (baseMapLayer.value) {
          imap.value.removeLayer(baseMapLayer.value);
        }
        if (extMapLayer.value) {
          imap.value.removeLayer(extMapLayer.value); // extraMapLayer
        }
        // 缺省地图边界样式确认（没有则加载）
        if (!aStyleList.value.mapDefStyle) {
          proxy.createDefStyle("mapDefStyle", aStyleList.value);
        }
        if (!aStyleList.value.mapSelStyle) {
          proxy.createDefStyle("mapSelStyle", aStyleList.value);
        }
        // 创建基本地图层
        baseMapLayer.value = proxy.createMapLayer(oMapInfos.base, conf.value); // 在mapLayer.js中
        imap.value.addLayer(baseMapLayer.value);
        baseMapLayer.value.setZIndex(0);
        // 创建扩展地图层（如，道路信息层）
        if (oMapInfos.ext && Object.keys(oMapInfos.ext).length !== 0) {
          // Object.keys(object).length === 0
          extMapLayer.value = proxy.createMapLayer(oMapInfos.ext, conf.value); // 在mapLayer.js中
          imap.value.addLayer(extMapLayer.value);
          extMapLayer.value.setZIndex(1);
        }
        sMapType.value = sMapTypeName;
      }
    };
    const getImg = (imgName = null) => {
      const imgObj = {
        extent: [0, 0, 700000, 1300000],
        url: "/mapres/maps/img/2000px-British_National_Grid.svg.png",
      };
      if (baseMapLayer.value) {
        imap.value.removeLayer(baseMapLayer.value);
      }
      if (extMapLayer.value) {
        imap.value.removeLayer(extMapLayer.value); // extraMapLayer
      }
      baseMapLayer.value = proxy.createImageLayer(imgObj);
      imap.value.addLayer(baseMapLayer.value);
      baseMapLayer.value.setZIndex(0);
    };
    /**
     * 根据hideLevel显示或隐藏边界线
     * 如果hideLevel为空，不做处理
     */
    const toggleByHideLevel = () => {
      // hideLevel为空时不做处理边界线的显隐
      if (hideLevel.value) {
        let mapLevel = imap.value.getView().getZoom();
        mapLevel = Math.floor(mapLevel * 100) / 100;
        if (mapLevel > hideLevel.value) {
          proxy.setGeoLayerVisible(false);
        } else {
          proxy.setGeoLayerVisible(true);
        }
      }
    };
    /* Method: bindMapEvent地图事件绑定
     * 地图的事件处理绑定
     * 参数：
     * 返回：
     */
    const bindMapEvent = () => {
      // 监听地图层级变化-- 显示地图级别信息(调试用)
      imap.value.getView().on("change:resolution", () => {
        let mapLevel = imap.value.getView().getZoom();
        mapLevel = Math.floor(mapLevel * 100) / 100;
        const iElementDIV = document.getElementById("mapLevel");
        if (iElementDIV) {
          iElementDIV.innerHTML = mapLevel;
        }
        // POI Cluster update
        POILayer.methods.updateClusterSwitch(mapLevel, 14);
        if (hideLevel.value) {
          if (mapLevel >= hideLevel.value) {
            proxy.setGeoLayerVisible(false);
          } else {
            proxy.setGeoLayerVisible(true);
          }
        }
        // 直角坐标系更新
        if (proxy.bShowCoordLayer) {
          proxy.redrawCoord();
        }
      });

      // 鼠标按下事件(如果有选中军标，关闭拖动，记录选中军标，获取当前位置，记录军标ID--name)
      imap.value.on("pointerdown", (evt) => {
        if (iAction.value && iAction.value.toLocaleLowerCase() === "plotting") {
          isMouseDown.value = true;
          // 获取地图实例
          const map = evt.map;

          const feature = map.forEachFeatureAtPixel(
            evt.pixel,
            function (feature) {
              // 只处理POI和PLOT类型数据
              if (feature.get("type") === "PLOT") {
                // feature.get('type') === 'POI' ||
                return feature;
              } else {
                feature = null;
                return feature;
              }
            }
          );
          if (feature) {
            dragPan.value.setActive(false);
            coordinate_.value = evt.coordinate;
            feature_.value = feature;
            iSelPlotID.value = feature.getProperties().gid; // 鼠标按下时，获取点击的军标ID
            console.log(PlottingLayer)
            PlottingLayer.mixins[0].methods.setPanel(iSelPlotID.value);
          }
        }
      });
      // 鼠标释放事件
      imap.value.on("pointerup", (evt) => {
        // if (!iAction.value) return
        if (iAction.value && iAction.value.toLocaleLowerCase() === "plotting") {
          if (feature_.value) {
            const geometry = feature_.value.getGeometry();
            let iType = geometry.getType().toLowerCase();
            // icon时由多个元素组成，需要避免选到元素？
            const selID = iSelPlotID.value; // 获取选择的军标ID （组id）
            if (!selID) return; // 有时释放会使selID为空，0903加此排错
            const shortName = selID.substr(0, 4);
            //  排除ddir单独处理
            if (
              shortName === "icon" ||
              shortName === "dire" ||
              shortName === "mult" ||
              shortName === "hand" ||
              shortName === "ddir"
            ) {
              iType = "point";
            }
            if (iType === "point") {
              // 删除原有的控制点
              PlottingLayer.methods.clearCtrlPoint();
              PlottingLayer.methods.addCtrlPoint(iSelPlotID.value);
            } else if (iType === "polygon" || iType === "linestring") {
              // 获取新的控制点
              const newCoord = geometry.getCoordinates();
              console.log(newCoord);
              // 修改xData中的控制点数据
              PlottingLayer.methods.updateCtrlPoint(iSelPlotID.value, newCoord);
              // 删除原有的控制点
              PlottingLayer.methods.clearCtrlPoint();
              // 创建控制点(gid会自动添加alt_前缀)
              PlottingLayer.methods.addCtrlPoint(iSelPlotID.value);
            } else if (iType === "circle") {
              const iCenterPost = geometry.getCenter();
              const iRadius = geometry.getRadius();
              const cp2 = [iCenterPost[0] + iRadius, iCenterPost[1]];
              // 已经将控制点变成圆心和控制点两个坐标，原来为：圆的控制点为[[圆心]，[半径，0]]  ==> 控制点2 [iCenterPost, [iCenterPost[0] + iRadius, iCenterPost[1]]]
              const newCoord = [iCenterPost, cp2];
              PlottingLayer.methods.updateCtrlPoint(iSelPlotID.value, newCoord);
              // 删除原有的控制点
              PlottingLayer.methods.clearCtrlPoint();
              // 创建控制点(gid会自动添加alt_前缀)
              PlottingLayer.methods.addCtrlPoint(iSelPlotID.value);
            }
            // 数据更新写入记录数组
            let plotElementID = iSelPlotID.value;
            if (plotElementID.substr(0, 4) === "alt_") {
              plotElementID = plotElementID.substr(4);
            }
            const plotElement = PlottingLayer.methods.getPlotFromXData(plotElementID);
            console.log(plotElement, iSelPlotID.value);
            if (plotElement) {
              PlottingLayer.methods.plotRecordUpdate(plotElement, "U");
              const attachText = PlottingLayer.methods.getPlotAttach(plotElementID); // 获取关联文字
              if (attachText) {
                for (let i = 0; i < attachText.length; i++) {
                  const txtID = attachText[i];
                  const txtElement = PlottingLayer.methods.getPlotFromXData(txtID);
                  if (txtElement) {
                    PlottingLayer.methods.plotRecordUpdate(txtElement, "U");
                  }
                }
              }
            }
          }
          if (isMouseDown.value) {
            dragPan.value.setActive(true);
            isMouseDown.value = false;
            coordinate_.value = null;
            feature_.value = null;
          }
        }
      });
      // 鼠标移动处理
      imap.value.on("pointermove", (evt) => {
        // 如果是拖动或其他绘制操作
        if (iAction.value || evt.dragging) {
          // 绘制军标事件
          if (
            iAction.value &&
            iAction.value.toLocaleLowerCase() === "plotting"
          ) {
            if (!coordinate_.value || !iSelPlotID.value) return; // 绘制完成后马上调整（程序会有两次点击操作--待定）
            if (feature_.value) {
              const deltaX = evt.coordinate[0] - coordinate_.value[0];
              const deltaY = evt.coordinate[1] - coordinate_.value[1];

              const geometry = feature_.value.getGeometry();
              const iType = geometry.getType().toLowerCase();
              if (iType === "point") {
                // 控制点,文字处理？
                const iProperties = feature_.value.getProperties();
                /* 类型（线：alt_LineString_70403，圆alt_Circle_685842，多边形（alt_Square_626442，alt_Star_724866）
                （alt_icon_816153，dire_894184），等alt_mult_getSLArrowPnts_8956745 */
                const xPart = iProperties.gid.split("_");
                if (xPart[0] === "text") {
                  // 如果是文字，创建控制点后退出
                  // 删除原有的控制点
                  return;
                }
                if (xPart[0] !== "alt") return; // 不是控制点退出
                const plotID = iProperties.gid.substr(4);
                const iType = xPart[1];
                let plotName = null;
                let ctrPnts = null;
                switch (iType) {
                  case "LineString": // 线的方式和多边形不一样
                    plotName = xPart[1]; // alt_{LineString}_70403
                    // 移动控制点
                    geometry.translate(deltaX, deltaY);
                    ctrPnts = PlottingLayer.methods.getCtrlPoint();
                    // 删除军标图层中的对应军标
                    PlottingLayer.methods.clearPlotByGID(plotID);
                    // 删除军标层中的控制点--不能删除（鼠标移动后已经更新到新位置）
                    // PlottingLayer.methods.clearCtrlPoint()
                    // 更新控制点信息
                    PlottingLayer.methods.updateCtrlPoint(plotID, ctrPnts);
                    // console.log(iProperties.gid, ctrPnts)
                    // 生成新的军标
                    PlottingLayer.methods.createBasePlot();
                    break;
                  case "Square": // 多边形
                  case "rect":
                  case "Star":
                  case "polygon":
                  case "infoBox":
                  case "flagPlus":
                  case "triangle":
                    plotName = xPart[1]; // alt_{LineString}_70403
                    // 移动控制点
                    geometry.translate(deltaX, deltaY);
                    ctrPnts = PlottingLayer.methods.getCtrlPoint();
                    // 删除军标图层中的对应军标
                    PlottingLayer.methods.clearPlotByGID(plotID);
                    // 删除军标层中的控制点--不能删除（鼠标移动后已经更新到新位置）
                    // PlottingLayer.methods.clearCtrlPoint()
                    // 更新控制点信息
                    ctrPnts.push(ctrPnts[0]);
                    PlottingLayer.methods.updateCtrlPoint(plotID, [ctrPnts]);
                    // console.log(iProperties.gid, ctrPnts)
                    // 生成新的军标
                    PlottingLayer.methods.createBasePlot();
                    break;
                  case "Circle":
                  case "unionRange":
                    plotName = xPart[1]; // Circle
                    // 将控制点根据鼠标拖动进行移动
                    geometry.translate(deltaX, deltaY);
                    // 在军标层中，获取控制点坐标（其中一个控制点已经在上面一步进行了修改）
                    ctrPnts = PlottingLayer.methods.getCtrlPoint();
                    // 删除军标图层中的对应军标，参数plotID已经删除了alt_前缀；实为gid
                    PlottingLayer.methods.clearPlotByGID(plotID);
                    // 更新控制点信息
                    PlottingLayer.methods.updateCtrlPoint(plotID, ctrPnts);
                    // 生成新的军标
                    PlottingLayer.methods.createBasePlot();
                    break;
                  case "text":
                    plotName = xPart[1]; // alt_{Text}_70703
                    // 文字控制点处理：如果是第一控制点，为移动位置。第二控制点也要跟随移动；
                    // 如是第二控制点，移动位置，缩放大小
                    // 获取控制点索引。确定是否为第一控制点
                    // let idx = feature_.value.getId()
                    // 处理第一控制点
                    if (feature_.value.getId() === 0) {
                      // tranAllCtrlPoint将所有控制点进行移动（根据参数），最后返回所有控制点坐标
                      ctrPnts = PlottingLayer.methods.tranAllCtrlPoint(
                        deltaX,
                        deltaY
                      );
                      PlottingLayer.methods.currPlot.cp = ctrPnts;
                    } else {
                      // 处理非第一控制点
                      geometry.translate(deltaX, deltaY);
                      // ctrPnts = PlottingLayer.methods.getCtrlPoint()[0]  // 会不会有空值情况？待定; 2文字有了第二个控制点后 注释！
                      ctrPnts = PlottingLayer.methods.getCtrlPoint();
                      // console.log(ctrPnts)
                    }
                    // 删除军标图层中的对应军标
                    PlottingLayer.methods.clearPlotByGID(plotID);
                    // 删除军标层中的控制点--不能删除（鼠标移动后已经更新到新位置）
                    // PlottingLayer.methods.clearCtrlPoint()
                    // 更新控制点信息
                    PlottingLayer.methods.updateCtrlPoint(plotID, ctrPnts);
                    // console.log(iProperties.gid, ctrPnts)
                    // 生成新的军标
                    PlottingLayer.methods.createTxtPlot();

                    break;
                  case "icon":
                    plotName = xPart[1]; // icon
                    // 将控制点根据鼠标拖动进行移动
                    geometry.translate(deltaX, deltaY);
                    // 在军标层中，获取控制点坐标（其中一个控制点已经在上面一步进行了修改）
                    ctrPnts = PlottingLayer.methods.getCtrlPoint(); // 可能需要添加JSON
                    // console.log(ctrPnts)
                    // 删除军标图层中的对应军标，参数plotID已经删除了alt_前缀；实为gid
                    PlottingLayer.methods.clearPlotByGID(plotID);
                    // console.log(PlottingLayer.methods.xData)
                    // 更新控制点信息
                    // PlottingLayer.methods.updateScaleRotate(plotID, ctrPnts)
                    PlottingLayer.methods.updateCtrlPointSVG(plotID, ctrPnts);
                    // 生成新的军标,根据新的控制点生成新军标，并添加到军标绘制层显示；
                    PlottingLayer.methods.createSVGPlot();
                    break;
                  case "dire":
                    plotName = xPart[1];
                    // 方法和icon相同
                    // 将控制点根据鼠标拖动进行移动
                    geometry.translate(deltaX, deltaY);
                    // 在军标层中，获取控制点坐标（其中一个控制点已经在上面一步进行了修改）
                    ctrPnts = PlottingLayer.methods.getCtrlPoint(); // 可能需要添加JSON
                    // console.log(ctrPnts)
                    // 删除军标图层中的对应军标，参数plotID已经删除了alt_前缀；实为gid
                    PlottingLayer.methods.clearPlotByGID(plotID);
                    // console.log(PlottingLayer.methods.xData)
                    // 更新控制点信息
                    // PlottingLayer.methods.updateScaleRotate(plotID, ctrPnts)
                    PlottingLayer.methods.updateCtrlPointSVG(plotID, ctrPnts);
                    // 生成新的军标,根据新的控制点生成新军标，并添加到军标绘制层显示；
                    PlottingLayer.methods.createSVGPlot();
                    break;
                  case "ddir":
                    // 将控制点根据鼠标拖动进行移动
                    geometry.translate(deltaX, deltaY);
                    // 在军标层中，获取控制点坐标（其中一个控制点已经在上面一步进行了修改）
                    ctrPnts = PlottingLayer.methods.getCtrlPoint(); // 可能需要添加JSON
                    // console.log(ctrPnts)
                    // 删除军标图层中的对应军标，参数plotID已经删除了alt_前缀；实为gid
                    PlottingLayer.methods.clearPlotByGID(plotID);
                    // console.log(PlottingLayer.methods.xData)
                    // 更新控制点信息
                    // PlottingLayer.methods.updateScaleRotate(plotID, ctrPnts)
                    PlottingLayer.methods.updateCtrlPointSVG(plotID, ctrPnts);
                    // 判断位置
                    const dx = ctrPnts[1][0] - ctrPnts[0][0]; // 水平方向差值
                    const dy = ctrPnts[1][1] - ctrPnts[0][1]; // 垂直方向差值
                    const iPlot = PlottingLayer.methods.getPlotFromXData(plotID); // 获得军标数据从xData中
                    const xTail = iPlot.name.substr(iPlot.name.length - 1, 1);
                    // console.log(xTail)
                    if (dy >= 0) {
                      if (xTail === "@") {
                        iPlot.name = iPlot.name.substr(
                          0,
                          iPlot.name.length - 1
                        );
                        PlottingLayer.methods.updatePlot(plotID, iPlot);
                        PlottingLayer.methods.plot_geometries =
                          PlottingLayer.methods.createSVGPlot(iPlot);
                        PlottingLayer.methods.geom2Featrue(
                          PlottingLayer.methods.plot_geometries
                        );
                      } else {
                        PlottingLayer.methods.plot_geometries =
                          PlottingLayer.methods.createSVGPlot(iPlot);
                        PlottingLayer.methods.geom2Featrue();
                      }
                    } else {
                      if (xTail === "@") {
                        PlottingLayer.methods.plot_geometries =
                          PlottingLayer.methods.createSVGPlot(iPlot);
                        PlottingLayer.methods.geom2Featrue();
                      } else {
                        iPlot.name = iPlot.name + "@";
                        PlottingLayer.methods.updatePlot(plotID, iPlot);
                        PlottingLayer.methods.plot_geometries =
                          PlottingLayer.methods.createSVGPlot(iPlot);
                        PlottingLayer.methods.geom2Featrue();
                      }
                    }
                    break;
                  case "mult":
                    plotName = xPart[1] + "_" + xPart[2];
                    // 方法和icon基本相同
                    // 将控制点根据鼠标拖动进行移动
                    geometry.translate(deltaX, deltaY);
                    // 在军标层中，获取控制点坐标（其中一个控制点已经在上面一步进行了修改）
                    ctrPnts = PlottingLayer.methods.getCtrlPoint(); // 可能需要添加JSON
                    // console.log(ctrPnts, geometry)

                    // 删除军标图层中的对应军标，参数plotID已经删除了alt_前缀；实为gid
                    PlottingLayer.methods.clearPlotByGID(plotID);
                    // 更新控制点信息-将数据写入xData
                    PlottingLayer.methods.updateCtrlPointSVG(plotID, ctrPnts);
                    // 生成新的军标,根据新的控制点生成新军标，并添加到军标绘制层显示；
                    PlottingLayer.methods.createPlot();
                    break;
                  default:
                }
                // 处理普通样式的军标（多边形，圆，线）
              } else if (
                iType === "polygon" ||
                iType === "circle" ||
                iType === "linestring"
              ) {
                const xPart = feature_.value.getProperties().gid;
                const iType = xPart.substr(0, 4);
                // 军标图形为基础类型，但是gid时svg类型
                if (
                  iType === "icon" ||
                  iType === "dire" ||
                  iType === "mult" ||
                  iType === "hand" ||
                  iType === "ddir"
                ) {
                  // svg方式时， 不论当前图形为什么类型，只显示控制点！
                  iSelPlotID.value = xPart;
                  // 如果没有控制点，创建。后面需要计算控制点的位置S
                  PlottingLayer.methods.clearCtrlPoint();
                  PlottingLayer.methods.addCtrlPoint(iSelPlotID.value);
                  // SVG控制点平移
                  PlottingLayer.methods.movePlotCtrlPnts(
                    iSelPlotID.value,
                    deltaX,
                    deltaY
                  );
                  // 清除控制点-以alt开头的
                  PlottingLayer.methods.clearCtrlPoint();
                  // 移动军标
                  PlottingLayer.methods.movePlogByID(
                    iSelPlotID.value,
                    deltaX,
                    deltaY
                  );
                } else {
                  PlottingLayer.methods.clearCtrlPoint();
                  geometry.translate(deltaX, deltaY);
                }
              }
              // 军标关联文字移动处理
              // 获取关军标信息
              const attachText = PlottingLayer.methods.getPlotAttach(
                iSelPlotID.value
              );
             
              PlottingLayer.methods.tranAttachTxt(attachText, deltaX, deltaY);
              coordinate_.value[0] = evt.coordinate[0];
              coordinate_.value[1] = evt.coordinate[1];
            }
          }
        } else {
          // 移动选择边界处理
          const pixel = imap.value.getEventPixel(evt.originalEvent); // 返回浏览器事件相对于视口的地图像素位置
          displayOverLayer(pixel);
        }
      });

      // 单击操作-如果是POI；展示其气泡信息；
      imap.value.on("singleclick", (evt) => {
        if (iAction.value) {
          // 如果有绘制操作，转交给相应的方法处理
          // 获取点击得到的要素
          const feature = imap.value.forEachFeatureAtPixel(
            evt.pixel,
            function (feature, layer) {
              // 目前需要处理POI和PlOT-标绘的数据
              if (
                feature.get("type") === "POI" ||
                feature.get("type") === "PLOT"
              ) {
                return feature;
              } else {
                return null;
              }
            }
          );
          // 标绘单击处理
          if (feature) {
            if (iAction.value.toLocaleLowerCase() === "plotting") {
              console.log(feature.get("gid"), "===", iSelPlotID.value);
              if (iSelPlotID.value === feature.get("gid")) {
                // 当前点击的军标，与上次相同
                const xPart = feature.get("gid");
                const iType = xPart.substr(0, 4);
                if (
                  iType === "icon" ||
                  iType === "dire" ||
                  iType === "mult" ||
                  iType === "hand"
                ) {
                  PlottingLayer.methods.clearCtrlPoint();
                  PlottingLayer.methods.addCtrlPoint(iSelPlotID.value);
                  feature_.value = feature;
                }
              } else {
                // 本次点击和上次点击的军标不相同
                const xPart = feature.get("gid");
                const iType = xPart.substr(0, 4);
                if (iType === "icon") {
                } else {
                  // 如果之前有绘制过控制点，需要先删除
                  if (iSelPlotID.value) {
                    // 之前已经有选择
                    // 删除已经有的
                  }
                  console.log("调用：plottClick 处理选择修改等,以下为测试！");
                  iSelPlotID.value = feature.get("gid"); // 保存当前所选军标的组id
                  // 调整军标样式，显示控制点-加载移动调整功能--先调整，完成后再优化显示
                  PlottingLayer.methods.addCtrlPoint(iSelPlotID.value);
                  feature_.value = feature;
                }
              }
            }
            // 绘制操作（不是标绘，是绘图）
            if (iAction.value.toLocaleLowerCase() === "drawing") {
              proxy.drawlayerSelectFeature(feature);
              if (iActType.value === "translate") {
                proxy.translateFeature(imap.value, feature);
              }
            }
          } else {
            // 没有选中feature
            if (iAction.value.toLocaleLowerCase() === "plotting") {
              if (iSelPlotID.value) {
                // 之前已经有选择
                // 删除已经有的
                PlottingLayer.methods.clearCtrlPoint();
                iSelPlotID.value = null;
              }
              // 清空选择的feature
              feature_.value = null;
            }
            // 绘制操作（绘图操作）
            if (iAction.value.toLocaleLowerCase() === "drawing") {
              if (selFeature.value) {
                proxy.drawLayerClearSelectFeature(selFeature.value);
                selFeature.value = null;
              }
            }
          }
        } else {
          // POI单击操作处理========================================
          // 获取点击得到的feature
          const feature = imap.value.forEachFeatureAtPixel(
            evt.pixel,
            (feature, layer) => {
              // 由function(feature, layer) {改成箭头函数
              // 如果有type属性就放返回此feature
              if (feature.get("type")) {
                // 如果type有信息，返回feature
                return feature;
              } else {
                return null;
              }
            }
          );
          if (feature) {
            if (feature.get("type").toUpperCase() === "POI") {
              // 新添加的图标缩放；判断是否启动了缩放图标功能（图标需要使用大图标）
              if (proxy.getIconZoomIO()) {
                // 提供图标缩放功能
                // console.log('缩放图标')
                const SZoom = proxy.zoomIconIO(feature);
                if (SZoom === "zoomout") {
                  // 如果是缩小图标，删除气泡，退出
                  const fID = "pop" + feature.getId();
                  proxy.closeBubbleById(fID); // 此方法在mapBubble.js
                  console.log(fID);
                  return;
                }
              }
              //  以下数据均为测试数据
              const xID = "pop" + feature.getId(); // 添加前缀，避免与闪烁冲突
              const xType = feature.get("dType"); // 如：医院
              const xCoord = feature.getGeometry().getCoordinates();
              const xBubble = feature.get("Bubble");
              // 气泡
              const iParam = {
                id: xID, // 信息点ID
                dType: xType,
                bubble: xBubble,
              };
              const aEvtCoord = evt.coordinate;
              proxy.addBubble(
                xID,
                xType,
                aEvtCoord,
                iParam,
                conf.value.RCS,
                imap.value
              ); // 地图中的feature坐标系统，是地图默认坐标系
            } else if (feature.get("type").toLowerCase() === "hot") {
              iHeatmap.value.clickheatgrid(feature);
            } else if (feature.get("type").toLowerCase() === "btn") {
              const oData = feature.get("Bubble");
              emit("poiPtnClick", oData);
            } else if (feature.get("type").toLowerCase() === "plot") {
              const sGid = feature.get("gid");
              const oPlotData = PlottingLayer.methods.getPlotFromXData(sGid); // 根据ID获取军标数据从xData中
              if (oPlotData) {
                const popInfo = oPlotData.pop;
                let xID;
                let xCoord;
                let xType;
                let iParam;
                if (popInfo) {
                  // 有提示数据
                  xID = "pop_" + sGid;
                  const aEvtCoord = evt.coordinate;
                  const xType = oPlotData.name;
                  iParam = {
                    id: xID, // 标绘气泡ID
                    dType: xType,
                    bubble: popInfo,
                  };
                  proxy.addBubble(
                    xID,
                    xType,
                    aEvtCoord,
                    iParam,
                    conf.value.RCS,
                    imap.value
                  );
                }
              }
            }
          }
        }
      });

      // 双击操作，根据不同条件显示信息
      imap.value.on("dblclick", (evt) => {
        // 如果当前为绘制操作，退出双击！
        if (iAction.value) {
          return;
        }
        const coordinate = evt.coordinate;
        const feature = imap.value.forEachFeatureAtPixel(
          evt.pixel,
          function (feature, layer) {
            return feature; // 获取有效双击点的feature
          }
        );
        if (feature) {
          console.log(feature.getGeometry());
          if (feature.get("type") === "POI") {
            // 处理POI
            // 测试闪烁功能
            const sType = feature.getGeometry().getType();
            if (sType === "Point") {
              const id = feature.getId();
              const aPnt = feature.getGeometry().getCoordinates();
              const sourceProj = imap.value.getView().getProjection();
              proxy.addCSSflash(id, aPnt, conf.value.RCS, imap.value); // 'EPSG:3857'
            }
          } else {
            // 当前操作为地图下钻，(注意：清除气泡及详情信息)
            const regName = feature.get("name");
            let zoomLevel = null;
            let cp = null;
            // 获取最佳视角(中心点，显示级别)
            const viewList = bestview.value ? bestview.value.viewList : [];
            for (let i = 0; i < viewList.length; i++) {
              if (viewList[i].regionName === regName) {
                zoomLevel = viewList[i].mapLevel;
                cp = viewList[i].coord;
                cp = olProj.transform(cp, "EPSG:4326", conf.value.RCS);
                break;
              }
            }
            if (!cp) {
              // 方法1：在geojson中获取中心店
              /* cp = feature.get('cp')
              const view = imap.value.getView()
              const zoom = view.getZoom()
              zoomLevel = zoom + 3 // 保存之前选择信息-修改显示级别

              */
              // 方法2:
              /* cp = coordinate // 鼠标点击位置
              const view = imap.value.getView()
              const zoom = view.getZoom()
              zoomLevel = zoom + 3
              */

              // 方法3：根据地理坐标范围获取中心点(作废)
              // cp = proxy.getFeatureCP(feature)

              // 方法4：使用getFeatureCPLv(oFeature, oView) mapbox.js中; 通过featrue计算中心点和显示级别
              // let rex = proxy.getFeatureCP(feature)
              const oCPLv = proxy.getFeatureCPLv(feature, imap.value); // 在mapBase.jsz中
              if (oCPLv.cp) {
                cp = oCPLv.cp;
              } else {
                cp = coordinate;
              }
              if (oCPLv.lv) {
                zoomLevel = oCPLv.lv;
              } else {
                const zoom = imap.value.getView().getZoom();
                zoomLevel = zoom + 3;
              }

              // 方法5：使用第三方模块获取中心点
              // let geo = feature.getGeometry()
              // console.log(geo.getType())
              // if (geo.getType() === 'Polygon' || geo.getType() === 'MultiPolygon') {
              //   let Points = geo.getCoordinates()
              //   console.log(Points)
              //   let turfLine = turf.lineString(Points) // 创建turf数据
              //   console.log(turfLine)
              // }
            }
            // 根据下钻信息，重新定位地图 https://www.giserdqy.com/secdev/openlayers/19686/
            mapDisplay(regName, cp, zoomLevel, conf.value.RCS, true, true);
          }
        }
      });
    };

    /* Method: mapDisplay
     * 根据给定的地图信息，显示地图
     * 参数：
     * regionName：区域名称
     * centerPoint：中心点坐标
     * zLevel：地图缩放级别
     * isMark: 是否记录到 mapList
     * isUpdate：是否更新数据；默认更新数据
     */
    const mapDisplay = (
      regionName,
      centerPoint,
      zLevel,
      iSRS = "EPSG:4326",
      isMark = true,
      isUpdate = true
    ) => {
      // 保存之前选择信息
      if (isMark) {
        mapList.value.push({
          region: curRegion.value,
          cp: centerPos.value,
          zoomLevel: currLevel.value,
        });
      }
      curRegion.value = regionName;
      // 设置当前区域地图
      const geoMap = "/mapres/maps/json/" + curRegion.value + ".json";
      imap.value.removeLayer(geoMapLayer.value);
      geoMapLayer.value = new VectorLayer({
        // ol.layer.Vector
        source: new VectorSource({
          // ol.source.Vector
          url: geoMap,
          format: new GeoJSON(), // ol.format.GeoJSON
        }),
        // 设置地图默认样式
        style: aStyleList.value.mapDefStyle, // mapDefStyle.value
      });
      imap.value.addLayer(geoMapLayer.value);
      // 调整层级关系
      geoMapLayer.value.setZIndex(5);

      currLevel.value = zLevel;
      let cp = null;
      if (iSRS !== conf.value.RCS) {
        // 'EPSG:4326'  -- 此步可以忽略！！！
        cp = olProj.transform(centerPoint, "EPSG:4326", conf.value.RCS);
      } else {
        cp = centerPoint;
      }
      centerPos.value = cp; // 保存之前选择信息-修改中心点
      imap.value.getView().animate({ center: cp, zoom: currLevel.value });
    };

    // 标绘时显示需要的边界（行政区域线）
    const areaDisplay = (strAreaName) => {
      // 设置当前区域地图
      const geoMap = "/mapres/maps/json/" + strAreaName + ".json";
      try {
        imap.value.removeLayer(geoMapLayer.value);
        geoMapLayer.value = new VectorLayer({
          // ol.layer.Vector
          source: new VectorSource({
            // ol.source.Vector
            url: geoMap,
            format: new GeoJSON(), // ol.format.GeoJSON
          }),
          // 设置地图默认样式
          style: aStyleList.value.mapSelStyle,
        });
      } catch (e) {
        imap.value.removeLayer(geoMapLayer.value);
        geoMapLayer.value = new VectorLayer({
          // ol.layer.Vector
          source: new VectorSource({
            // ol.source.Vector
            url: "/mapres/maps/json/china.json",
            format: new GeoJSON(), // ol.format.GeoJSON
          }),
          // 设置地图默认样式
          style: mapDefStyle.value,
        });
      } finally {
        imap.value.addLayer(geoMapLayer.value);
        geoMapLayer.value.setZIndex(5);
      }
    };

    // 地图回退 GoBack
    const GoBack = () => {
      if (mapList.value.length < 1) return;
      const preMap = mapList.value.pop();
      const curRegion = preMap.region;
      const centerPos = preMap.cp;
      const currLevel = preMap.zoomLevel;
      mapDisplay(curRegion, centerPos, currLevel, conf.value.RCS, false, true);
    };

    /* Method: drawBbox
     * 绘制范围框
     */
    const drawBbox = () => {
      iAction.value = "Plotting";
      iActType.value = "bbox";
      clearSelectZone(); // 清除鼠标选择区域(边界线)
      PlottingLayer.methods.startPlotting(imap.value);
      PlottingLayer.methods.setPlotType(iActType.value);
      PlottingLayer.methods.addInteraction();
      // 绘制范围盒子
      // 停止绘制
      // PlottingLayer.methods.stopPlotting()
    };
    /* Method: clearBBox
     * 不显示范围框（从图层中清除）
     */
    const clearBBox = () => {
      proxy.delShareDataByID("bbox"); // sID
    };
    /* Method: showBBox
     * 显示范围框
     */
    const showBBox = (bbox = bbox.value) => {
      // 清除旧的范围框
      clearBBox();
      if (!bbox) return;
      const cp1 = [bbox[0], bbox[1]];
      const cp2 = [bbox[0], bbox[3]];
      const cp3 = [bbox[2], bbox[3]];
      const cp4 = [bbox[2], bbox[1]];
      const iGeom = new LineString([cp1, cp2, cp3, cp4, cp1]);
      const iFeature = new Feature(iGeom);
      iFeature.setId("bbox");
      iFeature.set("type", "PLOT");
      iFeature.set("gid", "bbox");

      // 设置样式
      iFeature.setStyle(
        new Style({
          fill: new Fill({
            // ol.style.Fill
            color: "rgba(0,0,0,0)",
          }),
          stroke: new Stroke({
            // ol.style.Stroke
            color: "#00FDFF",
            width: 2,
            lineDash: [10, 10],
          }),
        })
      );
      // 将绘制的军标加入军标层
      shareLayer.value.getSource().addFeature(iFeature); // 原来的gridLayer格式有变化，改成shareLayer
    };
    // 返回范围框地理坐标
    const getBBox = () => {
      return bbox.value;
    };

    /**
     * @description 清除所层的数据
     * @param null
     * @return null
     */
    const clearAll = () => {
      // 删除气泡和闪烁
      proxy.clearAllOverlay();
      // 删除poi数据
      POILayer.methods.clearPOIData();
      // 删除热力数据（网格删除）
      iHeatmap.value.clearHeatData();
      // 删除标绘数据
      PlottingLayer.methods.clearData();
      // 动画层
      // 临时层(绘制的范围框也要删除吗？)
      proxy.clearShareLayerData();
    };

    /**
     * @description 删除所有层数据（保留热力网格）
     * @param null
     * @return null
     */
    const clearAllData = () => {
      // 删除气泡和闪烁
      proxy.clearAllOverlay();
      // 删除poi数据
      POILayer.methods.clearPOIData();
      // 删除热力数据（heatgrid类型不删除网格）
      const sType = iHeatmap.value.getHeatmapType();
      if (sType === "heatgrid") {
        iHeatmap.value.clearHeatGridData();
      } else {
        iHeatmap.value.clearHeatData();
      }
      // 删除标绘数据
      PlottingLayer.methods.clearData();
      // 动画层
      // 临时层(绘制的范围框也要删除吗？)
      proxy.clearShareLayerData();
    };

    /**
     * @description 清除所有的气泡
     * @param null
     * @return null
     */
    const constclearAllBubble_del = () => {
      // 和删除clearAllPopup功能相同--名称不同
      iBubble.value.clearAllBubble();
    };
    /**
     * @description 更新气泡--POI移动后位置有变更（待定）
     * @param null
     * @return null
     */
    const updateBubble_del = () => {
      const popList = iBubble.value.getBubbleList();
      let ilngLat = null;
      if (popList.length > 0) {
        for (const i in popList) {
          ilngLat = popList[i].coord;
          const pos = imap.value.project(ilngLat);
          popList[i].position = pos;
        }
      }
    };

    const mapSize = computed(() => {
      const styleObj = {
        width: props.mapWidth,
        height: props.mapHeight,
      };
      return styleObj;
    });

    onMounted(() => {
      // 添加China2000坐标
      proxy.addCRS4490(); // mapProj.js中
      initSource();
      initMap();
      dragPan.value = getFun(); // 标绘（修改时需要停止拖拽）
      bindMapEvent();
      POILayer.methods.initPOILayer(
        imap.value,
        aStyleList.value,
        sIconType.value
      ); // 添加POI层
      proxy.createShareLayer(imap.value);
    });

    return {
      selTest,
      selColor,
      imap,
      conf,
      bbox,
      bestview,
      mapDefStyle,
      curRegion,
      currLevel,
      centerPos,
      mapList,
      baseMapLayer,
      extMapLayer,
      geoMapLayer,
      gridLayer,
      featureOverlay,
      sMapType,
      sIconType,
      aStyleList,
      iSelect,
      iSelPlotID,
      iAction,
      iActType,
      selFeature,
      dragPan,
      isMouseDown,
      coordinate_,
      feature_,
      hideLevel,
      map,
      iBubble,
      iHeatmap,
      iPoi,
      iAnim,
      iPlotting,
      Prt,
      GoBack,
      switchMap,
      getPOIData,
      toggleCluster,
      setClusterDistance,
      getImg,
      savexData2DB,
      showPlotFile,
      mapDisplay,
      switchIconType,
      getPNGMap,
      showGrid,
      hideGrid,
      showData2,
      stopFlash,
      setScale,
      txtPnts,
      printPNG,
      printPDF,
      showPlotPanel,
      plotScale,
      getSaveData,
      setLoadData,
      createPlotFileID,
      loadPlotfromFile,
      selectPlot,
      onColorChange,
      onAdjust,
      getRegionDataByName,
      getBBoxByName,
      updateBBox,
      mapRefresh,
      toggleByHideLevel,
      areaDisplay,
      drawBbox,
      showBBox,
      getBBox,
      clearAll,
      clearAllData,
      constclearAllBubble_del,
      updateBubble_del,
      mapSize,
      clearSelectZone,
      boxZoom
    };
  },
});
</script>
<template>
  <div class="mapCard" style="width: 100%; height: 100%">
    <!-- :style="mapSize"-->
    <!-- 地图挂接点https://www.jianshu.com/p/64802fff1d80 -->
    <div :id="mapId" class="card-map" ref="map">
      <div id="mouse-position"></div>
      <div id="mapLevel"></div>
      <Bubble ref="iBubble"></Bubble>
      <!-- 热力图（普通）-->
      <HeatmapLayer ref="iHeatmap"></HeatmapLayer>
      <!-- Feature POI Layer -->
      <POILayer ref="iPoi"></POILayer>
      <!-- 动画层 -->
      <AnimLayer ref="iAnim"></AnimLayer>
      <!-- 军标绘制层 -->
      <PlottingLayer ref="iPlotting"></PlottingLayer>
      <!-- 闪烁容器 -->
      <div id="flash_container" style="display: none"></div>
      <!-- 气泡容器 -->
      <div id="pop-container" style="display: none"></div>
      <!-- 打印 -->
      <printer ref="Prt"></printer>
    </div>
    <!-- 演示用容器 none-->
    <div id="demo" style="display: none; z-index: 99">
      <button
        @click="
          measureByType('Polygon', [
            [
              [119.86748590429684, 32.50224837014309],
              [119.9629296298828, 32.45706750436945],
              [119.98730554541012, 32.5361191314865],
              [119.86748590429684, 32.50224837014309],
            ],
          ])
        "
      >
        测量
      </button>
      <button @click="toggleCoord(true)">直角坐标</button>
      <button @click="setIconZoomIO(false)">关闭图标缩放</button>
      <button @click="startAnimaLoop()">开始动画Loop</button>
      <button
        @click="
          createPath(
            '123',
            [
              [130.490823, 31.59542],
              [113.542241, 22.386853],
            ],
            true,
            'poiLayer',
            1
          )
        "
      >
        绘制路径1
      </button>
      <button @click="startPathAnima('123', 'plane', 2200000, 320)">
        开始动画1
      </button>
      <button
        @click="
          createTwoPointPath(
            '456',
            [128.659168, 35.267453],
            [113.542241, 22.386853]
          )
        "
      >
        绘制路径2
      </button>
      <button @click="startPathAnima('456', 'plane', 2200, 32)">
        开始动画2
      </button>
      <button @click="delPathByID('456')">删除路径</button>
      <button @click="delAllPath()">删除所有路径</button>
      <button @click="delSpriteByID('456')">删除指定精灵</button>
      <button @click="delAllSprite()">删除所有精灵</button>
      <button
        @click="
          createSinglePath(
            '789',
            [121.309448, 24.991412],
            [113.542241, 22.386853]
          )
        "
      >
        创建单一路径
      </button>
      <button @click="startPathAnima('789', 'plane', 2200, 32)">
        开始动画3
      </button>

      <button @click="stopAnimaLoop()">结束动画Loop</button>
      <!-- <button @click="createPath('123',[[0,0],[113000,2200000]])">绘制路径</button> 放在动画层IO  animLayerIO.js -->
      <button @click="GoBack()">返回上级</button>
      <button @click="switchMap('dark')">切换夜视地图</button>
      <button @click="switchMap('satellite')">切换卫星地图</button>
      <button @click="getPOIData()">POI展示</button>
      <button @click="clearHeatGridData()">删除热力数据</button>
      <button @click="destroyHeatmapLayer()">删除热力层</button>
      <button
        @click="
          isPointInPolygon(
            [100.36678622969443, 22.814785279689843],
            [
              [
                [108.35971653196168, 22.977604816017248],
                [108.25897172111989, 22.84084937983002],
                [108.37032121340663, 22.733302305115103],
                [108.49404281157155, 22.809897627715827],
                [108.35971653196168, 22.977604816017248],
              ],
            ]
          )
        "
      >
        inPolygon
      </button>
      <button @click="startTranslate()">开始移动</button>
      <button @click="startDrawByType('Point', false)">开始绘制</button>
      <select name="public-choice" v-model="selTest" @change="drawTypeChange()">
        <option value="Point">点</option>
        <option value="LineString">线</option>
        <option value="Polygon">面</option>
        <option value="Circle">圆</option>
        <option value="Box">矩形</option>
      </select>
      <button @click="drawCoordByLonLat([108.3631, 22.8192])">坐标绘制</button>
      <button @click="drawCircleByLonLat([108.3631, 22.8192], 10000)">
        圆绘制
      </button>
      <button @click="getFeatureLonLat()">获取坐标</button>
      <button @click="getMeasureVal()">获取测量值</button>
      <button @click="delFeature()">删除测试</button>
      <button @click="cleanAllDrawData()">删除绘制数据*</button>
      <button @click="endDraw()">结束绘制</button>
      <button @click="destroyDrawLayer()">销毁绘画层</button>
      <button @click="startPlotting(true)">开始标绘</button
      ><!-- drawing.js文件中 -->
      <button @click="startPlotting(false)">结束标绘</button>
      <button @click="stopFlash('test01')">删除闪烁</button>
      <!-- <button @click="openTopLabel()">打开顶牌</button> -->
      <button @click="openTopLabel('polygon')">打开顶牌</button>
      <button @click="closeTopLabel()">关闭顶牌</button>
      <button @click="showAllBubbleByType('Polygon', 'normal')">
        显示所有气泡
      </button>
      <button @click="showGrid()">显示网格</button>
      <button @click="hideGrid()">删除网格</button>
      <button @click="clearAllData()">删除数据</button>
      <button @click="onSolDataTest()">方案测试</button>
      <button @click="onSolDataTest2()">方案测试plus</button>
      <button @click="onSolDataUpdateTest()">更新文字</button>
      <button @click="delPlotByID('dire_1624869822854')">删除路径军标</button>
      <button @click="delPlotByID('cy1-370911370911129')">删除路径军标1</button>
      <button @click="delPlotByID('route_cy1-370911370911130')">
        删除路径军标2
      </button>
      <button @click="toggleCluster()">切换Cluster类型</button>
      <button @click="setClusterDistance(30)">修改聚集的融合长度</button>
      <button @click="selAnimRoad('line-002')">选择道路</button>
      <!--sc12345-->
      <button @click="selAnimRoad('line-001')">选择道路2</button>
      <button @click="cleanAnimRoad()">清除选择道路</button>
      <button
        @click="
          updateAnimBubbleByID('line-001', {
            summary: '修改成功',
            修改: '正确123',
          })
        "
      >
        更新道路气泡
      </button>
      <button @click="cleanAllAnimBubble()">删除所有动画气泡</button>
      <button @click="cleanAnimBubbleByID('line-001')">删除气泡1</button>
      <button @click="createAnimBubbleByID('line-001')">创建气泡</button>
      <button @click="redrawAnimBubbleByID('line-001')">重绘制</button>
      <button @click="moveSprite('869592046782054', [120.767814, 27.999273])">
        移动精灵
      </button>
      <button @click="animSpite('869592046782054', 100)">前进一步</button>
      <button @click="selectSpriteByID('869592046782054')">选择精灵</button>
      <button @click="selectSpriteByID('CAR869592046782')">选择精灵2</button>
      <button @click="selectSpriteByGIDIO('line-002')">选择精灵组</button>
      <button @click="cleanSelSpriteByGIDIO()">清除精灵组</button>
      <button
        @click="
          changeSpriteState(
            '869592046782054',
            'info',
            { stat: '修改状态测试' },
            'spt_'
          )
        "
      >
        setSpriteState
      </button>
      <button @click="cleanSpriteState('869592046782054')">
        clSpriteState
      </button>
      <!-- <button @click="testSocket()">webSocket</button> -->
      <button @click="testSocket()">初始化socket</button>
      <button
        @click="
          joinTrackRoom('2G_thkRKgFxE1GzASQ6n7dLSzJiogZhn3sXSiZLV', [
            '3F434046D7D7475CDA50F1C38F01F3F1',
            'RFDW-4501-0003',
          ])
        "
      >
        加入room
      </button>
      <button
        @click="
          joinTrackRoom('3G_thkRKgFxE1GzASQ6n7dLSzJiogZhn3sXSiZLV', [
            'CAR869592046782',
          ])
        "
      >
        加入room2
      </button>
      <!-- <button @click="joinTrackRoom('1','2')">加入room</button> -->
      <button
        @click="leaveTrackRoom('2G_thkRKgFxE1GzASQ6n7dLSzJiogZhn3sXSiZLV')"
      >
        退出room
      </button>
      <button @click="leaveAllTrackRoom()">退出全部房间</button>
      <button @click="testDictInfos()">debug</button>
      <button @click="toggleScale()">比例尺</button>
      <button @click="setScaleCoord('100px', '30px')">scale左下</button>
      <button @click="addCompass('10px', '10px', '50px', '100px')">
        添加指南针
      </button>
      <button @click="delCompass()">删除指南针</button>
      <button @click="clearAnimLayerData()">删除</button>
      <button @click="zoomIconByIdIO('RFGC-4501-0002', true)">
        根据ID缩放图标
      </button>
      <button
        @click="
          regionSelectIO(
            [[108.36252952049882, 22.833582438470486]],
            652,
            'EPSG:4326'
          )
        "
      >
        区域选择-圆
      </button>
      <button
        @click="
          regionSelectIO(
            [
              [108.35640907341599, 22.82670997757789],
              [108.35835098272483, 22.831340094747773],
              [108.36388120271303, 22.830717567150614],
              [108.36210815508322, 22.826671068362913],
              [108.35640907341599, 22.82670997757789],
            ],
            0,
            'EPSG:4326'
          )
        "
      >
        区域选择poly
      </button>
      <button @click="clearAllZoominIO()">清除所有变大图标</button>
      <button @click="testRegSel()">测试区选</button>
      <button @click="scaleStrokewidthByID('line-001', 3, 'animLayer')">
        路线选择1
      </button>
      <button @click="scaleStrokewidthByID('line-002', 3, 'animLayer')">
        路线选择2
      </button>
      <button
        @click="
          scaleStrokewidthByID(
            'mult_getSSArrowPnts_1625455783703',
            3,
            'plotLayer'
          )
        "
      >
        tPlot
      </button>
      <button
        @click="
          scaleStrokewidthByID(
            'mult_dashArrowPnts_1625455780176',
            3,
            'plotLayer'
          )
        "
      >
        tPlot2
      </button>
      <button
        @click="
          clearStrokewidthscale(
            'mult_getSSArrowPnts_1625455783703',
            'plotLayer'
          )
        "
      >
        cPlot
      </button>
      <button @click="getcoordArrCP()">点列中心</button>
      <button @click="ttt()">test</button>
      <button @click="getImg()">test图像地图</button>
      <button
        @click="
          drawPolyByLonLat(
            [
              [
                [119.2637507633277, 27.108601096475283],
                [117.56152603290901, 25.03230753548023],
                [123.5718491070349, 26.846401628979265],
                [122.75226096121186, 27.928636506039453],
                [119.2637507633277, 27.108601096475283],
              ],
            ],
            '#0000FF'
          )
        "
      >
        poly
      </button>
      <button
        @click="
          drawLineByLonLat(
            [
              [119.2637507633277, 27.108601096475283],
              [117.56152603290901, 25.03230753548023],
              [123.5718491070349, 26.846401628979265],
              [122.75226096121186, 27.928636506039453],
            ],
            '#00FFFF'
          )
        "
      >
        line
      </button>
      <button
        @click="
          drawCircleByLonLat(
            [119.2637507633277, 27.108601096475283],
            10000,
            '#666666'
          )
        "
      >
        circle
      </button>
      <input id="file" type="file" @change="loadPlotfromFile" />
      <button @click="savexData2DB()">保存导入数据</button>
      <button @click="getViewCenter()">获取视图中心</button>
      <button @click="showPlotFile('PLOT1655287906916')">打开标绘文件1</button>
      <button @click="showPlotFile('PLOT1655609333131')">打开标绘文件2</button>
      <button @click="setGeoLayerVisible(false)">隐藏</button>
      <button @click="setGeoLayerVisible(true)">显示</button>
      <button @click="getPlotFileByID('PLOT1655609333131')">
        获取标绘文件信息
      </button>
      <button @click="clonePlotFileByID('PLOT1655609333131', 'newPlotName')">
        temp
      </button>
      <button @click="setView('广东省')">视角</button>
      <button @click="clearPOIData()">删除POI</button>
      <button @click="mapDisplay('测试', [0, 0], 12)">视角2</button>
      <input id="fid" />
      <button @click="getFeatureCenterByIDTest()">获取feature中心</button>
      <button @click="switchIconType('cartoon')">图标类型</button>
      <button @click="getPNGMap('a2', '300', null)">打印test</button>
      <button @click="setOnceSign(true)">单次绘制</button>
      <button @click="setOnceSign(false)">多次绘制</button>
    </div>
  </div>
</template>
<style scoped lang='scss'>
#map-container {
  height: 100%;
}
.ol-attribution,
.ol-zoom {
  display: none;
}
#mouse-position {
  float: left;
  color: #f00;
  position: absolute;
  right: 18%;
  bottom: 25px;
  width: 320px;
  height: 20px;
  z-index: 2;
  font-weight: bolder;
}
#mapLevel {
  float: left;
  color: #00008b;
  position: absolute;
  right: 17%;
  bottom: 25px;
  height: 20px;
  z-index: 2;
  font-weight: bold;
  border: 1px solid #f00;
}
#demo {
  background: rgba(0, 0, 0, 0.7);
  border-radius: 0.3em;
  box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
  color: #fff;
  left: 1em;
  line-height: 1.5em;
  top: 1em;
  padding: 0.5em 1em;
  position: absolute;
}
</style>,
<style lang="scss">
.ol-tooltip {
  position: relative;
  background: rgba(0, 0, 0, 0.5);
  border-radius: 4px;
  color: #fff;
  padding: 4px 8px;
  opacity: 0.7;
  white-space: nowrap;
  font-size: 12px;
}
.ol-tooltip-measure {
  opacity: 1;
  font-weight: bold;
}
.ol-tooltip-static {
  background-color: #fc3;
  color: #000;
  border: 1px solid #fff;
  &:before {
    border-top-color: #fc3;
  }
}
.ol-tooltip-measure:before,
.ol-tooltip-static:before {
  border-top: 6px solid rgba(0, 0, 0, 0.5);
  border-right: 6px solid transparent;
  border-left: 6px solid transparent;
  content: "";
  position: absolute;
  bottom: -6px;
  margin-left: -7px;
  left: 50%;
}
</style>